package dream

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"

	"gopkg.in/ini.v1"
)

func encodeBase64(b []byte) string {
	return base64.StdEncoding.EncodeToString(b)
}

func encryptText(key, text []byte) []byte {
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	b := encodeBase64(text)
	ciphertext := make([]byte, aes.BlockSize+len(b))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}
	cfb := cipher.NewCFBEncrypter(block, iv)
	cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
	return ciphertext
}

func decodeBase64(s string) ([]byte, error) {
	data, err := base64.StdEncoding.DecodeString(s)
	if err != nil {
		return nil, err
	}
	return data, nil
}
func decryptText(key, text []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(text) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}
	iv := text[:aes.BlockSize]
	text = text[aes.BlockSize:]
	cfb := cipher.NewCFBDecrypter(block, iv)
	cfb.XORKeyStream(text, text)
	return decodeBase64(string(text))
}

func LoadJson(file string) (*JSONRead, JSONS) {

	conf := ""
	if file == "config" || len(file) == 0 {
		conf = workPath
		conf += "cfg/" + AppName() + ".conf.json"
	} else if file == "service" {
		conf = workPath
		conf += "cfg/" + AppName() + ".service.json"
	} else {
		conf = workPath
		conf += file
	}
	b, err := ioutil.ReadFile(conf)
	if err != nil {
		return nil, ""
	}

	j := make(map[string]interface{})
	err = json.Unmarshal(b, &j)
	if err != nil {
		b, err = decryptText([]byte("application/x-www-form-urlencode/hidog"), b)
		if err != nil {
			return nil, ""
		}
		j := make(map[string]interface{})
		err = json.Unmarshal(b, &j)
		if err != nil {
			return nil, ""
		}
	}

	return &JSONRead{JSONT: j}, JSONS(string(b))
}

func LoadIni(file string) (*INI, string) {

	conf := ""
	if file == "config" || len(file) == 0 {
		conf = workPath
		conf += "cfg/" + AppName() + ".conf.ini"
	} else if file == "service" {
		conf = workPath
		conf += "cfg/" + AppName() + ".service.ini"
	} else {
		conf = workPath
		conf += file
	}
	b, err := ioutil.ReadFile(conf)
	if err != nil {
		return nil, ""
	}
	cf, err := ini.LoadSources(ini.LoadOptions{
		SkipUnrecognizableLines: true,
		Insensitive:             true,
	}, b)
	if err != nil {
		b, err = decryptText([]byte("application/x-www-form-urlencode/hidog"), b)
		if err != nil {
			return nil, ""
		}
		cf, err = ini.LoadSources(ini.LoadOptions{
			SkipUnrecognizableLines: true,
			Insensitive:             true,
		}, b)
		if err != nil {
			return nil, ""
		}
	}
	var j = &INI{}
	j.INIT = make(map[string]map[string]string)
	alls := cf.Sections()
	for _, v := range alls {
		keys := v.Keys()
		if len(keys) > 0 {
			vv := make(map[string]string)
			for _, kv := range keys {
				vv[kv.Name()] = kv.Value()
			}
			j.INIT[v.Name()] = vv
		}
	}

	return j, string(b)
}
